﻿using System;
using Unity.Collections;
using UnityEditor.Rendering.LookDev;
using UnityEngine;
using UnityEngine.Rendering;

/// <summary>
/// 灯光渲染
/// </summary>
public class Lighting
{
    const string bufferName = "Lighting";
    CommandBuffer buffer = new CommandBuffer
    {
        name = bufferName
    };

    ScriptableRenderContext context;
    CullingResults cullingResults;

    /// <summary>
    /// 方向光数量
    /// </summary>
    static int dirLightCountId = Shader.PropertyToID("_DirectionalLightCount");
    /// <summary>
    /// 方向光颜色
    /// </summary>
    static int dirLightColorsId = Shader.PropertyToID("_DirectionalLightColors");
    /// <summary>
    /// 方向光方向
    /// </summary>
    static int dirLightDirectionsId = Shader.PropertyToID("_DirectionalLightDirections");
    static int dirLightShadowDataId = Shader.PropertyToID("_DirectionalLightShadowData");

    /// <summary>
    /// 最大平行光数量
    /// </summary>
    const int maxDirLightCount = 4;
    static Vector4[] dirLightColors = new Vector4[maxDirLightCount];
    static Vector4[] dirLightDirections = new Vector4[maxDirLightCount];
    static Vector4[] dirLightShadowData = new Vector4[maxDirLightCount];

    Shadowing shadowing = new Shadowing();

    public void Setup(ScriptableRenderContext context, CullingResults cullingResults, ShadowSettings shadowSettings)
    {
        this.context = context;
        this.cullingResults = cullingResults;

        buffer.BeginSample(bufferName);
        ExecuteBuffer();
        {
            shadowing.Setup(context, cullingResults, shadowSettings);
            SetupLights(cullingResults);
            shadowing.Render();
        }
        buffer.EndSample(bufferName);
        ExecuteBuffer();
    }

    private void SetupLights(CullingResults result)
    {
        NativeArray<VisibleLight> lightArray = result.visibleLights;
        int count = 0;
        for (int i = 0; i < lightArray.Length; i++)
        {
            VisibleLight light = lightArray[i];
            if (light.lightType == LightType.Directional)
            {
                // 筛选出类型为 Directional
                SetupDirectionalLight(ref light, count++);
                if (count >= maxDirLightCount)
                {
                    break;
                }
            }
        }

        buffer.SetGlobalInt(dirLightCountId, count);
        buffer.SetGlobalVectorArray(dirLightColorsId, dirLightColors);
        buffer.SetGlobalVectorArray(dirLightDirectionsId, dirLightDirections);
        buffer.SetGlobalVectorArray(dirLightShadowDataId, dirLightShadowData);
    }

    private void SetupDirectionalLight(ref VisibleLight light, int index)
    {
        dirLightColors[index] = light.finalColor;   // finalColor 已包含了灯光强度
        dirLightDirections[index] = -light.localToWorldMatrix.GetColumn(2);
        dirLightShadowData[index] = shadowing.ReserveDirShadows(light.light, index);
    }

    public void Cheanup()
    {
        shadowing.CleanUp();
    }

    void ExecuteBuffer()
    {
        context.ExecuteCommandBuffer(buffer);
        buffer.Clear();
    }
}
